﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Xsl;
using System.Xml.XPath;
using Microsoft.Practices.ESB.Exception.Management;
using Microsoft.Practices.ESB.Itinerary;
using Microsoft.Practices.ESB.Itinerary.Services;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Bam.EventObservation;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.XLANGs.BaseTypes;

namespace BizTalk.ESB.Extensions.Helpers
{
    [Serializable]
    public class BusinessDataTracking : ItineraryServiceDataMappingConfig
    {
        public string BamActivityName { get; set; }
        
        public BusinessDataTracking()
        {
            base.DataMappings = new Dictionary<string, string>();
        }

        public void TrackBam(XmlDocument Message, IBaseMessageContext MsgContext, IPipelineContext PipeContext, IItineraryStep ItineraryStep, string BamTypeName, BamEventTypes BamEventType
                , string BamTackingConfigString, int BamFlushThreshold, int TimeoutSeconds, string BamConnectionString, bool StopOnError)
        {
            if (String.IsNullOrEmpty(BamTypeName))
            {
                throw new ArgumentException("BAM Activity Definition name cannot be null", "BamTypeName");
            }
            else if (String.IsNullOrEmpty(BamTackingConfigString))
            {
                throw new ArgumentException("BAM Event Type name cannot be null", "BamEventType");
            }
            else
            {
                var activityId = ItineraryStep.ServiceInstanceId;
                var xmlMsg = Message;
                var bamTrackingConfig = BuildTrackingConfigArray(BamTackingConfigString, xmlMsg, MsgContext, StopOnError);

                System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - Building BAM Writer...");
                BamWriter bamWriter;
                if (BamEventType == BamEventTypes.Integrated)
                {
                    bamWriter = new BamWriter(PipeContext);
                }
                else
                {
                    bamWriter = new BamWriter(BamEventType, BamConnectionString, BamFlushThreshold, TimeoutSeconds);
                }

                if (bamTrackingConfig.Length > 0)
                {
                    bamWriter.BeginActivity(BamTypeName, activityId);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - BeginActivity = " + activityId);
                    bamWriter.UpdateActivity(BamTypeName, activityId, bamTrackingConfig);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - UpdateActivity = " + activityId);
                    bamWriter.EndActivity(BamTypeName, activityId);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - EndActivity = " + activityId);
                    if (BamFlushThreshold <= 0)
                    {
                        bamWriter.Flush();
                        System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - Flush = " + activityId);
                    }
                }
                else
                {
                    EventLogger.Write("Failed to retrieve BAM Field key-value pairs.", MethodInfo.GetCurrentMethod());
                }
            }
        }

        public void TrackBam(XLANGMessage Message, IItineraryStep ItineraryStep, string BamTypeName, BamEventTypes BamEventType
                    , string BamTackingConfigString, int BamFlushThreshold, int TimeoutSeconds, string BamConnectionString, bool StopOnError)
        {
            if (String.IsNullOrEmpty(BamTypeName))
            {
                throw new ArgumentException("BAM Activity Definition name cannot be null", "BamTypeName");
            }
            else if (String.IsNullOrEmpty(BamTackingConfigString))
            {
                throw new ArgumentException("BAM Event Type name cannot be null", "BamEventType");
            }
            else
            {
                var activityId = ItineraryStep.ServiceInstanceId;
                var bamTrackingConfig = BuildTrackingConfigArray(BamTackingConfigString, Message, StopOnError);

                System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - Building BAM Writer...");
                BamWriter bamWriter = new BamWriter(BamEventType, BamConnectionString, BamFlushThreshold, TimeoutSeconds);

                if (bamTrackingConfig.Length > 0)
                {
                    bamWriter.BeginActivity(BamTypeName, activityId);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - BeginActivity = " + activityId);
                    bamWriter.UpdateActivity(BamTypeName, activityId, bamTrackingConfig);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - UpdateActivity = " + activityId);
                    bamWriter.EndActivity(BamTypeName, activityId);
                    System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - EndActivity = " + activityId);
                    if (BamFlushThreshold <= 0)
                    {
                        bamWriter.Flush();
                        System.Diagnostics.Trace.WriteLine("BusinessDataMonitor - Flush = " + activityId);
                    }
                }
                else
                {
                    EventLogger.Write("Failed to retrieve BAM Field key-value pairs.", MethodInfo.GetCurrentMethod());
                }
            }
        }
    }
}
